package org.ykh.common.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.ykh.common.annotation.SyncTransactional;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ykh
 */
@Aspect
@Component
@Slf4j
//最高优先级，保证包裹其他切面
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SyncAspect {

    private final ConcurrentHashMap<String,Object> lockMap = new ConcurrentHashMap<>();

    @Around("@annotation(org.ykh.common.annotation.SyncTransactional)")
    public Object sync( ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        final Signature signature = proceedingJoinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        // 获取SyncTransactional注解
        SyncTransactional syncTransactional = method.getAnnotation(SyncTransactional.class);

        String lockKey = syncTransactional.value();
        final Object lock ;
        switch (lockKey){
            case "class":
                lock = proceedingJoinPoint.getTarget().getClass();
                break;
            case "this":
                lock = proceedingJoinPoint.getTarget();
                break;
            default:
                //TODO:从set中获取一个对象，作为锁
                lock = lockMap.get(lockKey);
        }
        if (lock == null) {
            throw new RuntimeException("无锁对象");
        }
        try {
            if (log.isDebugEnabled()) {
                log.debug("synchronized({})开始",lock);
            }
            synchronized (lock) {
                return proceedingJoinPoint.proceed();
            }
        }finally {
            if (log.isDebugEnabled()){
                log.debug("synchronized({})结束",lock);
            }
        }
    }


}
